package com.yixing.demo.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yixing.demo.constants.Constants;
import com.yixing.demo.mapper.LoveMusicMapper;
import com.yixing.demo.model.Music;
import com.yixing.demo.model.Result;
import com.yixing.demo.model.User;
import com.yixing.demo.service.MusicService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Slf4j
@RequestMapping("/music")
@RestController
public class MusicController {
    @Value("${music.local.path}")
    private String SAVE_PATH;//不能加static修饰，否则配置文件的内容注入不进来

    @Autowired
    private MusicService musicService;
    @Autowired
    LoveMusicMapper loveMusicMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    ObjectMapper objectMapper;

    @RequestMapping("/upload")
    public Result<Boolean> insertMusic(String singer, MultipartFile filename, HttpSession session,
                                       HttpServletResponse resp) throws JsonProcessingException {
        if(singer.equals("")) {
            return new Result<>(-1, "您还未填写歌手名", false);
        }
        String filenameAndType = filename.getOriginalFilename();
        if(filenameAndType.equals("")) {
            return new Result<>(-1, "您还未选择要上传的歌曲文件", false);
        }
        //检查当前音乐是否已经上传过，上传过则不能重复上传
        String title = filenameAndType.substring(0, filenameAndType.lastIndexOf("."));
        if(musicService.inspectMusicIsExist(title) != null) {
            return new Result<>(-1, "该歌曲已经上传过，不能重复上传", false);
        }
        String localFilename = SAVE_PATH + filenameAndType;
        File localFile = new File(localFilename);
        if(!localFile.exists()) {
            localFile.mkdirs();
        }
        try {
            filename.transferTo(localFile);
        } catch (IOException e) {
            e.printStackTrace();
            return new Result<>(-1, "上传歌曲到服务器失败", false);
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String time = simpleDateFormat.format(new Date());
        String url = "music/get?path=" + title;
        User userInfo = (User) session.getAttribute(Constants.USER_SESSION_KEY);
        Integer userId = userInfo.getId();
        int ret = musicService.insertMusic(title, singer, time, url, userId);
        if(ret == 1) {
            try {
                resp.sendRedirect("/musiclist.html");
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

            //将歌曲上传到数据库和服务器上后，也要把数据库中的歌曲信息存入redis
            log.info("歌曲开始上传到redis****************************************************************");
            Music music1 = musicService.inspectMusicIsExist(title);
            String str = objectMapper.writeValueAsString(music1);
            redisTemplate.opsForList().rightPush("seekMusic:", str);
            return new Result<>(1, "上传歌曲成功", true);//这个if分支的返回一定要有
        }else {
            localFile.delete();//这一步一定要写
            return new Result<>(-1, "上传歌曲到数据库失败", false);
        }
    }



    @RequestMapping("/get")
    public ResponseEntity<byte[]> play(String path) {
        log.info("准备播放音乐");
        try {
            byte[] bytes = Files.readAllBytes(new File(SAVE_PATH + path).toPath());
            return ResponseEntity.ok(bytes);
        } catch (IOException e) {
            e.printStackTrace();
            return null;//这个返回一定要有
        }
    }



    @RequestMapping("/delete")
    public Result<Boolean> delete(Integer id) throws JsonProcessingException {
        Music music = musicService.inspectMusicIsExistById(id);
        if(music == null) {
            return new Result<>(-1, "没有你要删除的音乐", false);
        }else {
            int ret = musicService.deleteMusicById(id);
            if (ret == 1) {
                String musicUrl = music.getUrl();
                String musicName = musicUrl.substring(musicUrl.lastIndexOf("=") + 1);
                String localFilePath = SAVE_PATH + "/" + musicName + ".mp3";
                File localFile = new File(localFilePath);
                if (localFile.delete()) {
                    loveMusicMapper.deleteLoveMusicByMusicId(id);

                    //从redis中删除歌曲
                    log.info("开始从redis中删除数据****************************************************************");
                    List<String> values = redisTemplate.opsForList().range("seekMusic:", 0, -1);
                    for (String str : values) {
                        Music music1 = objectMapper.readValue(str, Music.class);
                        if(music1.getId() == id) {
                            redisTemplate.opsForList().remove("seekMusic:", 1, str);
                        }
                    }

                    return new Result<>(1, "删除音乐成功", true);
                } else {
                    return new Result<>(-1, "删除服务器中的音乐失败", false);
                }
            } else {
                return new Result<>(-1, "删除数据库中的音乐失败", false);
            }
        }
    }



    @RequestMapping("/deleteBatch")
    public Result<Boolean> deleteBatch(@RequestParam(value = "id[]") List<Integer> ids) throws JsonProcessingException {
        int sum = 0;
        for (int i = 0; i < ids.size(); i++) {
            Integer id = ids.get(i);
            Music music = musicService.inspectMusicIsExistById(id);
            if(music == null) {
                return new Result<>(-1, "没有你要批量删除的音乐中的某个音乐", false);
            }else {
                int ret = musicService.deleteMusicById(id);
                if (ret == 1) {
                    String musicUrl = music.getUrl();
                    String musicName = musicUrl.substring(musicUrl.lastIndexOf("=") + 1);
                    String path = SAVE_PATH + "/" + musicName + ".mp3";
                    File file = new File(path);
                    if (file.delete()) {
                        loveMusicMapper.deleteLoveMusicByMusicId(id);
                        sum++;
                    }else {
                        return new Result<>(-1, "批量删除服务器中的音乐失败", false);
                    }
                } else {
                    return new Result<>(-1, "批量删除数据库中的音乐失败", false);
                }
            }

            //从redis中批量删除歌曲
            log.info("开始从redis中批量删除数据****************************************************************");
            List<String> values = redisTemplate.opsForList().range("seekMusic:", 0, -1);
            for (String str : values) {
                Music music1 = objectMapper.readValue(str, Music.class);
                if(music1.getId() == id) {
                    redisTemplate.opsForList().remove("seekMusic:", 1, str);
                }
            }
        }
        if(sum == ids.size()) {
            return new Result<>(1, "批量删除音乐成功", true);
        }else {
            return new Result<>(-1, "批量删除音乐失败", false);
        }
    }



    @RequestMapping("/seekMusic")
    public Result<List<Music>> seekMusic(@RequestParam(required = false) String title) throws JsonProcessingException {
        List<Music> list = new ArrayList<>();
        if(title != null) {
            list = musicService.seekMusicByTitle(title);
        }else {
            List<String> values = redisTemplate.opsForList().range("seekMusic:", 0, -1);
            if(values.size() == 0) {
                log.info("开始从数据库中查出歌曲数据****************************************************************");
                list = musicService.seekMusicByNoTitle();
                //将数据库中的数据存入redis
                for(Music music : list) {
                    String str = objectMapper.writeValueAsString(music);
                    redisTemplate.opsForList().rightPush("seekMusic:", str);
                }
            }else {
                log.info("开始从redis中查出歌曲数据****************************************************************");
                for (String str : values) {
                    Music music = objectMapper.readValue(str, Music.class);
                    list.add(music);
                }
            }
        }
        return new Result<>(1, "查询歌曲成功", list);
    }
}
